package com.huchao.www.Listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.huchao.www.dao.StudentMapper;
import com.huchao.www.exception.MyException;
import com.huchao.www.pojo.StudentData;
import com.huchao.www.service.impl.StudentServiceImpl;
import com.huchao.www.utils.ExcelPatternUtile;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson2.JSON;
import org.springframework.dao.DuplicateKeyException;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @Description:
 * @BelongsProject: background-management-v10
 * @BelongsPackage: com.huchao.www.Listener
 * @Author: 亖思
 * @CreateTime: 2023/3/12 10:12
 * @Version: 1.0
 */
@Slf4j
public class StudentDataListener implements ReadListener<StudentData> {
    /**
     * 每隔100条存储数据库，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<StudentData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 错误信息集合
     */
    private static List<String> errorList = new ArrayList<>();
    /**
     * 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private StudentMapper studentMapper;

    static String msg = "success";

    private List<String> majorList;

    private List<String> collegeList;

    private List<String> classList;

    private List<Integer> noList;

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param studentMapper
     */
    public StudentDataListener(StudentMapper studentMapper) {
        this.studentMapper = studentMapper;
        majorList = studentMapper.findAllMajor();
        collegeList = studentMapper.findAllCollege();
        classList = studentMapper.findAllClassNum();
        noList = studentMapper.findAllNo();
    }

    public StudentDataListener() {
    }

    /**
     * @param data
     * @param analysisContext
     */
    @SneakyThrows
    @Override
    public void invoke(StudentData data, AnalysisContext analysisContext) {
        IsErrorExcel(data, analysisContext);

        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 〈判断Excel内容格式是否正确〉
     *
     * @param data:
     * @param analysisContext:
     * @Author: 亖思
     * @Date: 2023/3/14 14:05
     * @return: void
     **/
    private void IsErrorExcel(StudentData data, AnalysisContext analysisContext) {
        int nowRowNum = analysisContext.readRowHolder().getRowIndex() + 1;

        if (data.getStuNo() == null) {
            errorList.add("第" + nowRowNum + "行，第A列，学号数据为空");
        }else if(noList.contains(data.getStuNo())){
            errorList.add("第" + nowRowNum + "行，第A列，学号已经存在");
        }

        if (data.getStuName() == null) {
            errorList.add("第" + nowRowNum + "行，第B列，姓名数据为空");
        }

        if (data.getStuIdCard() == null) {
            errorList.add("第" + nowRowNum + "行，第C列，身份证数据为空");
        } else if (!Pattern.matches(ExcelPatternUtile.IDENTITY, data.getStuIdCard())) {
            errorList.add("第" + nowRowNum + "行，第C列," + ExcelPatternUtile.IDENTITY_MSG);
        }

        if (data.getStuState() == null) {
            errorList.add("第" + nowRowNum + "行，第D列，状态数据为空");
        }

        if (data.getCollege() == null) {
            errorList.add("第" + nowRowNum + "行，第E列，学院数据为空");
        } else if (!collegeList.contains(data.getCollege())) {
            errorList.add("第" + nowRowNum + "行，第E列，" + data.getCollege() + "不存在");
        }

        if (data.getMajor() == null) {
            errorList.add("第" + nowRowNum + "行，第F列，专业数据为空");
        } else if (!majorList.contains(data.getMajor())) {
            errorList.add("第" + nowRowNum + "行，第F列，" + data.getMajor() + "不存在");
        }

        if (data.getClassNum() == null) {
            errorList.add("第" + nowRowNum + "行，第G列，班级数据为空");
        } else if (!classList.contains(data.getClassNum())) {
            errorList.add("第" + nowRowNum + "行，第G列，" + data.getClassNum() + "不存在");
        }

        if (data.getStuRepoTime() == null) {
            errorList.add("第" + nowRowNum + "行，第H列，报道时间数据为空");
        } else if (!Pattern.matches(ExcelPatternUtile.DATE_TIME1, data.getStuRepoTime().toString())) {
            errorList.add("第" + nowRowNum + "行，第H列，" + ExcelPatternUtile.DATE_TIME1_MSG);
        }
    }

    /**
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        saveData();

        log.info("所有数据解析完成！");
        log.info("共解析到" + errorList.size() + "条数据，错误");
        log.info(collegeList.size() + "个学院");
        log.info(classList.size() + "个班级");
        log.info(majorList.size() + "个专业");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据，开始存储数据库！", cachedDataList.size());
        //使用batchInsert,所有数据一次性插入
        if(errorList.size() == 0){
            studentMapper.addStuByStudentDataList(cachedDataList);
        }
        log.info("存储数据库成功！");
    }

    /**
     * 〈获取返回信息--默认返回“success”,有错误则返回报错内容〉
     *
     * @Author: 亖思
     * @Date: 2023/3/15 8:46
     * @return: java.lang.String
     **/
    public static String getMsg() {
        if (errorList.size() > 0) {
            msg = "";
            for (String str : errorList
            ) {
                msg += str + "\t";
            }
        }
        //存储完成清空报错内容
        errorList.clear();
        return msg;
    }
}
